home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 June: Reference Library / Dev.CD Jun 95 / Dev.CD Jun 95.toast / What's New? / Sample Code / QuickTime Sample Code / DTS QT Utilities.Apr-95 / DTSQTUtilities.c < prev    next >
Encoding:
Text File  |  1995-04-16  |  37.7 KB  |  1,192 lines  |  [TEXT/MPCC]

  1. /*
  2.     File:        DTSUtilities.c
  3.  
  4.     Contains:    QuickTime functions.
  5.  
  6.     Written by:    DTS
  7.  
  8.     Copyright:    © 1994-1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.        <1>         12/17/94    khs        first file
  13.        
  14. */
  15.  
  16.  
  17. // INCLUDES
  18. #include "DTSQTUtilities.h"
  19.  
  20.  
  21. // MOVIE TOOLBOX FUNCTIONS
  22.  
  23. /*______________________________________________________________________
  24.     QTUIsQuickTimeInstalled - Test if QuickTime is installed.
  25.  
  26. pascal Boolean    QTUIsQuickTimeInstalled(void) 
  27.  
  28. DESCRIPTION
  29.     InitQuickTime will test if QuickTime is present. We are not interested in the QuickTime
  30.     version.
  31. */
  32.  
  33. pascal Boolean QTUIsQuickTimeInstalled(void) 
  34. {
  35.     long         qtVersion;
  36.     OSErr     anErr;
  37.  
  38.     anErr = Gestalt(gestaltQuickTime, &qtVersion); DebugAssert(anErr == noErr);
  39.     if (anErr != noErr)
  40.         return false;        // no QT present
  41.     else
  42.         return true;
  43. }
  44.  
  45.  
  46. /*______________________________________________________________________
  47.     QTUIsQuickTimeCFMInstalled - Test if the QuickTime CFM libraries are installed and in the 
  48.     right place.
  49.  
  50. pascal Boolean    QTUIsQuickTimeCFMInstalled(void) 
  51.  
  52. DESCRIPTION
  53.     QTUIsQuickTimeCFMInstalled will test if the CFM QuickTime libraries are present (QuickTime 
  54.     PowerPlug, for instance), and if the libraries are still present (this because the libraries are 
  55.     registered once when Gestalt finds then during runtime, and the end user might delete these, 
  56.     or move them to another location later)(.
  57. */
  58.  
  59. #ifdef powerc
  60. pascal Boolean QTUIsQuickTimeCFMInstalled(void) 
  61. {
  62.     OSErr     anErr;
  63.     long         qtFeatures; 
  64.  
  65. // Test if the library is registered.
  66.     anErr = Gestalt(gestaltQuickTimeFeatures, &qtFeatures); DebugAssert(anErr == noErr);
  67.     
  68.     if (!(  (anErr == noErr)  &&  (qtFeatures & (1 << gestaltPPCQuickTimeLibPresent))  )) // not true
  69.           return false;
  70.           
  71. // Test if a function is available (the library is not moved from the Extension folder),  this is the 
  72. // trick to be used concerning testing if a function is available via CFM.
  73.  
  74.     if   ( ! CompressImage )
  75.         return false;     
  76.     else 
  77.         return true;
  78. }
  79. #endif powerc
  80.  
  81.  
  82. /*______________________________________________________________________
  83.     QTUGetQTVersion - Return the current QuickTime version number.
  84.  
  85. pascal long QTUGetQTVersion()
  86.  
  87. DESCRIPTION
  88.     QTUGetQTVersion is a simple function that will return the current QuickTime version number,
  89.     and if QuickTime is not installed it will return 0L.  The high order word defines the version number, 
  90.     for instance 0x0161 defines version 1.6.1.
  91.     
  92.     You could also directly assign a boolean value stating if a certain version is true by using this
  93.     kind of an expression:
  94.     
  95.     Boolean gHasQT2.0 = (( QTUGetQTVersion() >>  16) & 0xFFFF) >= 0x200;
  96.     
  97. EXAMPLE
  98.     if( (QTUGetQTVersion() >> 16) < 0x150 ) return; // need to work with QT 1.5 or higher.
  99. */
  100.  
  101. pascal long QTUGetQTVersion()
  102. {
  103.     long version;
  104.     
  105.     if(Gestalt(gestaltQuickTime, &version) == noErr)
  106.         return version;
  107.     else
  108.         return 0L;
  109. }
  110.  
  111.  
  112. /*______________________________________________________________________
  113.      QTUPrerollMovie - Preroll the movie before you start the movie.
  114.  
  115. pascal OSErr QTUPrerollMovie(Movie theMovie)
  116.  
  117. theMovie                the destination movie for this operation
  118.  
  119. DESCRIPTION
  120.     QTUPrerollMovie will get the movie time,  duration and preferred rate, and Preroll the movie 
  121.     based on this information. Note that StartMovie already does a PrerollMovie so in that case this 
  122.     is not needed, this is also true of the standard controller that handles the start of movie
  123.     when the keyboard or mouse is used.
  124. */
  125.  
  126. pascal OSErr QTUPrerollMovie(Movie theMovie) 
  127. {
  128.     TimeValue         aTimeValue;
  129.     TimeValue         aMovieDur;
  130.     Fixed                 aPreferredRate;
  131.     OSErr                anErr = noErr;
  132.  
  133.     aTimeValue          = GetMovieTime(theMovie, NULL);
  134.     aMovieDur         = GetMovieDuration(theMovie);
  135.     aPreferredRate  = GetMoviePreferredRate(theMovie);
  136.  
  137.     anErr = PrerollMovie(theMovie, aTimeValue, aPreferredRate); DebugAssert(anErr == noErr);
  138.     
  139.     return anErr;
  140. }
  141.  
  142.  
  143. pascal Boolean QTUFileFilter(ParmBlkPtr theParamBlock);
  144.  
  145.  
  146. /*______________________________________________________________________
  147.     QTUGetMovie - Get a movie resource from a specific file.
  148.  
  149. pascal Movie QTUGetMovie(FSSpec *theFSSpec, short *theRefNum, short *theResID)
  150.  
  151. theFSSpec                the specific FSSpec used, if NULL the system will use a standard dialog
  152.                             box for the end user to select a file
  153. theRefNum            this is the specific file ref num we want to use later
  154. theResID                this is the specific resource ID we want to use later
  155.  
  156. DESCRIPTION
  157.     QTUGetMovie will get a movie resource out from a specified file, if the FSSpec is not provided
  158.     then the function will use a StandardGetFilePreview to select the movie.
  159. */
  160.  
  161. pascal Movie QTUGetMovie(FSSpec *theFSSpec, short *theRefNum, short *theResID)
  162. {
  163.     OSErr                    anErr;
  164.     SFTypeList            aTypeList = {MovieFileType, 0, 0, 0};
  165.     StandardFileReply    aReply;
  166.     Movie                    aMovie = NULL;
  167.     
  168. // If we are provided with an FSSpec then use it, otherwise do a standardgetfile dialog box and 
  169. // ask the end user to get it.
  170.     if(theFSSpec == NULL || theFSSpec->vRefNum == 0)
  171.     {    
  172.         StandardGetFilePreview( NewFileFilterProc(QTUFileFilter), 1, aTypeList, &aReply);
  173.         if(! aReply.sfGood)
  174.             return NULL;
  175.         
  176.         *theFSSpec = aReply.sfFile;
  177.     }
  178.  
  179.     // We should have now a usable FSSpec, just double check this once again before continuing.
  180.     DebugAssert(theFSSpec != NULL); if(theFSSpec == NULL) return NULL;
  181.     
  182.     anErr = OpenMovieFile(theFSSpec, theRefNum, fsRdPerm); DebugAssert(anErr == noErr);
  183.     
  184.     if(anErr == noErr)
  185.     {
  186.         Str255    aMovieName;
  187.         Boolean    wasChanged;
  188.         
  189.         *theResID = 0;                    // want first movie
  190.         
  191.         anErr = NewMovieFromFile(&aMovie, *theRefNum, theResID,
  192.                                                     aMovieName, newMovieActive, &wasChanged);
  193.         DebugAssert(anErr == noErr);
  194.  
  195.         CloseMovieFile(*theRefNum);
  196.     }
  197.     
  198.     if(anErr != noErr)
  199.         return NULL;
  200.     else
  201.         return aMovie;
  202. }
  203.  
  204.  
  205. /*______________________________________________________________________
  206.     QTUFileFilter - Skeleton file filter to be used with various MovieToolbox standard dialog utilities.
  207.  
  208. pascal Boolean QTUFileFilter(ParmBlkPtr theParamBlock)
  209.  
  210. theParamBlock        specifies a particular ParmBlockPtr
  211.  
  212. DESCRIPTION
  213.     QTUFileFilter is a skeleton file filter to be used with various MovieToolbox standard dialog utilities
  214.     The function will return a boolean false if it encounters any errors from the Movie toolbox.
  215. */
  216.  
  217. pascal Boolean QTUFileFilter(ParmBlkPtr theParamBlock)
  218. {
  219.     return false;
  220. }
  221.  
  222.  
  223. /*______________________________________________________________________
  224.       QTUSaveMovie - Save and flatten a movie resource into a  file.
  225.  
  226. pascal OSErr QTUSaveMovie(Movie theMovie)
  227.  
  228. theMovie            defines the movie to be saved into a file
  229.  
  230. DESCRIPTION
  231.     QTUSaveMovie will provide a user dialog asking for a file name, and will then save the movie
  232.     into this file. Note that this function will also automatically flatten the movie so that  it's 
  233.     self-contained, and also make it cross-platform (by adding any possible resource forks to
  234.     the end of the data fork. The default name of the movie is also NEWMOVIE.MOV, this reflects
  235.     the way movie file names should be named for cross-platform support (Windows). The default
  236.     creator type is also 'TVOD' so that MoviePlayer will be the default application that opens the
  237.     movie file. If there's an existing movie file with the same name, it will be deleted.
  238. */
  239.  
  240.  
  241. pascal OSErr QTUSaveMovie(Movie theMovie)
  242. {
  243.     StandardFileReply    anSFReply;
  244.     OSErr anErr = noErr;
  245.     
  246.     DebugAssert(theMovie != NULL); if(theMovie == NULL) return invalidMovie;
  247.     
  248.     StandardPutFile("\pSave Movie as:" , "\pNEWMOVIE.MOV", &anSFReply); 
  249.     if(anSFReply.sfGood)
  250.     {
  251.  
  252.         FlattenMovieData(theMovie, flattenAddMovieToDataFork, &anSFReply.sfFile, 
  253.                                         'TVOD', smSystemScript, createMovieFileDeleteCurFile );
  254.         anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  255.     }
  256.         return anErr;
  257. }
  258.  
  259.  
  260. /*______________________________________________________________________
  261.     QTUFlattenMovieFile - Flatten a movie into a specified file.
  262.  
  263. pascal OSErr QTUFlattenMovieFile(Movie theMovie, FSSpec *theFile)
  264.  
  265. theMovie                defines the movie to be flattened
  266. theFile                    defines the target file
  267.  
  268. DESCRIPTION
  269.     FlattenMovie file will take an existing movie, flatten it into a temp file, and then move the
  270.     contents of the temp file into the specified FSSpec. This because there are cases where we 
  271.     can't flatten a movie in place. We will use TickCount as a temp file name.    
  272.     
  273.     Note that we need to dispose the movie inside this function? Why? Well, the file is open as
  274.     long as there's a pointer to it from the movie resource. And we need to delete the original 
  275.     movie file as part of the operation of swapping the files. 
  276. */
  277.  
  278. pascal OSErr QTUFlattenMovieFile(Movie theMovie, FSSpec *theFile)
  279. {
  280.     OSErr         anErr = noErr;
  281.     FSSpec         tempFile;
  282.     Str255     tempFileName;
  283.     
  284.     DebugAssert(theMovie != NULL); if(theMovie == NULL) return invalidMovie;
  285.     
  286.     // Create the needed temp file.
  287.     NumToString(TickCount(), tempFileName);
  288.         anErr = FSMakeFSSpec(theFile->vRefNum, theFile->parID, tempFileName, &tempFile);
  289.     if(anErr != fnfErr) return anErr;
  290.     
  291.     // Flatten the movie.
  292.     FlattenMovie(theMovie, flattenAddMovieToDataFork, &tempFile, 'TVOD', smSystemScript, 
  293.                             createMovieFileDeleteCurFile, 0, NULL);
  294.     anErr = GetMoviesError();
  295.     if(anErr != noErr)
  296.     {
  297.         FSpDelete(&tempFile);        // remove the temp file
  298.         return anErr;
  299.     }
  300.     
  301.     DisposeMovie(theMovie);
  302.     anErr = FSpDelete(theFile);  ReturnIfError(anErr);
  303.     anErr = FSpRename(&tempFile, theFile->name); ReturnIfError(anErr);
  304.     
  305.     return anErr;
  306. }
  307.  
  308.  
  309. // TRACKS AND MEDIA
  310.  
  311. /*______________________________________________________________________
  312.     QTUMediaTypeInTrack - Check if a particular media type is present in the movie.
  313.  
  314. pascal Boolean QTUMediaTypeInTrack(Movie theMovie, OSType theMediaType)
  315.  
  316. theMovie                    movie to be tested about the media type
  317. theMediaType            media type we want to test about
  318.  
  319. DESCRIPTION
  320.     QTUMediaTypeInTrack could be used to scan if a possible media type is present in the movie 
  321.     (video,sound, other media types).
  322. */
  323.  
  324. pascal Boolean QTUMediaTypeInTrack(Movie theMovie, OSType theMediaType)
  325. {
  326.     Track         aTrack = NULL;
  327.     long            aTrackCount = 0;
  328.     long            index;
  329.     OSType        aMediaType;
  330.     Boolean        haveMediaType = false;
  331.     
  332.     aTrackCount = GetMovieTrackCount(theMovie);
  333.     if(aTrackCount == 0)
  334.         return false;                // no tracks in movie
  335.     
  336.     for(index = 1; index <= aTrackCount; index++)
  337.     {
  338.         aTrack = GetMovieIndTrack(theMovie, index);
  339.         GetMediaHandlerDescription( GetTrackMedia(aTrack), &aMediaType, NULL, NULL);
  340.         
  341.         haveMediaType = ( aMediaType == theMediaType);
  342.         if(haveMediaType == true)
  343.             return true;
  344.     }
  345.     return false;            // didn't find the media type track in the movie
  346. }
  347.  
  348.  
  349. /*______________________________________________________________________
  350.     QTUGetTrackRect - Check if a particular media type is present in the movie.
  351.  
  352. pascal Rect QTUGetTrackRect(Track theTrack)
  353.  
  354. theTrack                track we are interested in concerning the rect information
  355.  
  356. DESCRIPTION
  357.     QTUMediaTypeInTrack will take a (visual) track and return the track's Rect boundaries that 
  358.     could be used later for various calculations of the visual track geometries.
  359.  
  360. ISSUES
  361.     Should we test if the track is a visual one and if so bail out? If so we need to send down a 
  362.     pointer to a Rect and return OSErrs.
  363. */
  364.  
  365. pascal Rect QTUGetTrackRect(Track theTrack)
  366. {
  367.     Rect         aRect = {0, 0, 0, 0};
  368.     Fixed    aTrackHeight;
  369.     Fixed    aTrackWidth;
  370.     OSErr    anErr;
  371.     
  372.     DebugAssert(theTrack != NULL);
  373.     if(theTrack == NULL)
  374.         return aRect;
  375.         
  376.     GetTrackDimensions(theTrack, &aTrackHeight, &aTrackWidth);
  377.     anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  378.     if(anErr != noErr)
  379.         return aRect;
  380.     
  381.     aRect.right = Fix2Long(aTrackWidth);
  382.     aRect.bottom = Fix2Long(aTrackHeight);
  383.     
  384.     return aRect;
  385. }
  386.  
  387.  
  388. /*______________________________________________________________________
  389.     QTUGetVideoMediaPixelDepth - Return the pixel depth of the current port where the media is 
  390.     presented.
  391.  
  392. pascal short QTUGetVideoMediaPixelDepth(Media theMedia,short index)
  393.  
  394. theMedia            visual media we want to test concerning pixel depths
  395. index                   index into the media sample we are interested in
  396.  
  397. DESCRIPTION
  398.     QTUGetVideoMediaPixelDepth will take a specified video media and an index into the media 
  399.     samples, and look up the pixel depth for the video sample.
  400. */
  401.  
  402. pascal short QTUGetVideoMediaPixelDepth(Media theMedia,short index)
  403. {
  404.     short aPixelDepth;
  405.     SampleDescriptionHandle anImageDesc = NULL;
  406.     OSType mediaType;
  407.     OSErr anErr;
  408.     
  409.     DebugAssert(theMedia != NULL);
  410.     DebugAssert(index > 0);
  411.     
  412.     // Test if we are indeed dealing with video media.
  413.     GetMediaHandlerDescription(theMedia, &mediaType, NULL, NULL);
  414.     if(mediaType != VideoMediaType)
  415.         return 0;
  416.         
  417.     anImageDesc = (SampleDescriptionHandle)NewHandle(sizeof(Handle)); DebugAssert(anImageDesc != NULL);
  418.     if(anImageDesc == NULL)
  419.         return 0;
  420.     
  421.     GetMediaSampleDescription(theMedia, index, anImageDesc);
  422.     anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  423.     
  424.     aPixelDepth = (* (ImageDescriptionHandle)anImageDesc)->depth;
  425.     
  426.     DisposeHandle((Handle)anImageDesc);
  427.     
  428.     return aPixelDepth;
  429. }
  430.  
  431.  
  432. /*______________________________________________________________________
  433.     QTUCountMediaSamples - Count the amount of known media samples in a movie.
  434.  
  435. pascal long QTUCountMediaSamples(Movie theMovie, OSType theMediaType)
  436.  
  437. theMovie                    the movie with the track(tracks).    
  438. theMediaType            the type of media we are interested in (video, sound and so on)
  439.  
  440. DESCRIPTION
  441.     QTUCountMediaSamples will take a specified movie and a media type, and calculate the amount 
  442.     of samples of this particular type. It could be used to find the total amount of video frames in a 
  443.     movie, or sound samples and so on.
  444.  
  445.     Note that if the movie is long, it will take a long time to go through all the samples, especially 
  446.     in the case of sound samples.
  447.  
  448. EXAMPLE:
  449.     nFrames = QTUCountMediaSamples(aSourceMovie, VideoMediaType); 
  450.  
  451. ISSUES
  452.     This function could be modified to count other types of samples by changing the flags definitions 
  453.     (nextTimeSyncSample for key frames and so on).
  454. */
  455.  
  456. pascal long QTUCountMediaSamples(Movie theMovie, OSType theMediaType)
  457. {
  458.     long numFrames = -1;
  459.     
  460.     short flags = nextTimeMediaSample + nextTimeEdgeOK;
  461.     TimeValue aDuration;
  462.     TimeValue theTime = 0;
  463.     
  464.     while(theTime >= 0)
  465.     {
  466.         numFrames++;
  467.         GetMovieNextInterestingTime(theMovie, flags, 1, &theMediaType, theTime, 0, &theTime, &aDuration);
  468.         flags = nextTimeMediaSample; // don't include the current time after the first interesting time
  469.     }
  470.     
  471.     return numFrames;
  472. }
  473.  
  474.  
  475. /*______________________________________________________________________
  476.     QTUGetDurationOfFirstMovieSample - Return the time value of the first sample of a certain 
  477.     media type.
  478.  
  479. pascal TimeValue  QTUGetDurationOfFirstMovieSample(Movie theMovie, OSType theMediaType)
  480.  
  481. theMovie                        the movie with the media track
  482. theMediaType                specified media type (VideoMediaType, SoundMediaType and so on)
  483.  
  484. DESCRIPTION
  485.     QTUGetDurationOfFirstMovieSample returns the duration of the first sample of a certain media 
  486.     in the movie. If there is no such sample, the duration is 0.
  487.  
  488.     This function could be used in known cases where all the samples are assumed to be of the same 
  489.     duration. For instance in such cases the frame count could be calculated as:
  490.  
  491.     framecount =
  492.              GetMovieDuration(theMovie)/QTUGetDurationofFirstMovieSample(theMovie, VideoMediaType);
  493.  
  494. */
  495.  
  496. pascal TimeValue  QTUGetDurationOfFirstMovieSample(Movie theMovie, OSType theMediaType)
  497. {
  498.     OSErr             anErr = noErr;
  499.     TimeValue        interestingDuration = 0;
  500.     short            timeFlags = nextTimeMediaSample+nextTimeEdgeOK;
  501.  
  502.     GetMovieNextInterestingTime(theMovie, timeFlags, (TimeValue)1, &theMediaType, 0, 
  503.                                                     fixed1, NULL, &interestingDuration);
  504.     anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  505.  
  506.     return interestingDuration;
  507. }
  508.  
  509.  
  510. /*______________________________________________________________________
  511.     QTUCountMaxSoundRate - Calculate the max sound data rate of a possible sound track
  512.    in the movie.
  513.  
  514. pascal OSErr QTUCountMaxSoundRate(Movie theMovie,long *theMaxSoundRate)
  515.  
  516. theMovie                        the movie with the sound track(tracks).    
  517. theMaxSoundRate            the final returned rate value.
  518.  
  519. DESCRIPTION
  520.     QTUCountMaxSoundRate (taken from the ConvertToMovieJr file) is a simple function that tries
  521.     to figure out the maximum sound track rate. This is done by looking at all of the sound tracks
  522.     in the source movie, and using the one with the highest sample rate (11khz, 22khz and so on),
  523.  
  524.     This number could then be used for calculating the maximum data rate by extracting the sound rate and 
  525.     this way we get a loose estimation how much is left for the video data rate.
  526.     
  527.     This is just an approximation, and a better function should take into account non-overlapping
  528.     sound tracks, stereo sound data rates, compressed sound tracks and so on.
  529. */
  530.  
  531. pascal OSErr QTUCountMaxSoundRate(Movie theMovie,long *theMaxSoundRate)
  532. {
  533.     short index, trackCount;
  534.     OSErr anErr = noErr;
  535.     
  536.     DebugAssert(theMovie != NULL); if(theMovie == NULL) return invalidMovie;
  537.     *theMaxSoundRate = 0; // just for security we place this value in here
  538.     
  539.     trackCount = GetMovieTrackCount(theMovie);
  540.     
  541.     for(index = 1; index <= trackCount; index++)
  542.     {
  543.         OSType     aTrackType;
  544.         Track        aTrack = NULL;
  545.         Media        aMedia = NULL;
  546.         
  547.         aTrack = GetMovieIndTrack(theMovie, index);  DebugAssert(aTrack != NULL);
  548.         aMedia = GetTrackMedia(aTrack); DebugAssert(aMedia != NULL);
  549.         anErr = GetMoviesError();  DebugAssert(anErr == noErr);
  550.         if(anErr != noErr) return anErr;
  551.         
  552.         GetMediaHandlerDescription(aMedia, &aTrackType, 0, 0);
  553.         if(aTrackType == SoundMediaType)
  554.         {
  555.             long aRate;
  556.             SampleDescriptionHandle aDesc = NULL;
  557.             
  558.             aDesc = (SampleDescriptionHandle)NewHandle(sizeof(SampleDescription)); DebugAssert(aDesc != NULL);
  559.             GetMediaSampleDescription(aMedia, 1, aDesc);
  560.             anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  561.             if(anErr != noErr)
  562.             {
  563.                 DisposeHandle((Handle)aDesc);
  564.                 continue;
  565.             }
  566.             
  567.             aRate = (*(SoundDescriptionHandle)aDesc)->sampleRate >> 16;
  568.             if(aRate > *theMaxSoundRate)
  569.                 *theMaxSoundRate = aRate;
  570.         }
  571.     }
  572.     return anErr;
  573. }
  574.  
  575.  
  576.  
  577. /*______________________________________________________________________
  578.     QTUGetMovieFrameCount - Return the amount of frames in the movie based on frame rate estimate.
  579.  
  580. pascal long QTUGetMovieFrameCount(Movie theMovie, long theFrameRate)
  581.  
  582. theMovie                    the movie we want to calculate the frame count for.            
  583. theFrameRate            the expected frame rate of the movie
  584.  
  585. DESCRIPTION
  586.     QTUGetMovieFrameCount is a simple operation that takes into account the duration of the movie,
  587.     the time scale and a suggested frame rate, and based on this will calculate the 
  588.     amount of frames needed in the movie. We assume that the frame rate will be uniform in the movie.
  589. */
  590.  
  591. pascal long QTUGetMovieFrameCount(Movie theMovie, long theFrameRate)
  592. {
  593.     long frameCount, duration, timescale;
  594.     float exactFrames;
  595.     
  596.     DebugAssert(theMovie != NULL); if(theMovie == NULL) return invalidMovie;
  597.  
  598.     duration         = GetMovieDuration(theMovie);
  599.     timescale         = GetMovieTimeScale(theMovie);
  600.     exactFrames    = (float)duration * theFrameRate;
  601.     
  602.     frameCount    = exactFrames / timescale / 65536;
  603.     
  604.     if(frameCount == 0)
  605.         frameCount = 1;            // we got to have at least one frame
  606.     
  607.     return frameCount;
  608. }
  609.  
  610.  
  611. /*______________________________________________________________________
  612.     QTUCopySoundTracks - Copy any sound track from the source movie to the destination movie.
  613.  
  614. pascal OSErr QTUCopySoundTracks(Movie theSrcMovie, Movie theDestMovie)
  615.  
  616. aSourceMovie                 movie from which to copy the sound tracks            
  617. aDestinationMovie             movie to which we will copy the sound tracks.    
  618.  
  619. DESCRIPTION
  620.     QTUCopySoundTracks will take any sound tracks from the source movie, and copy these over to the
  621.     destination movie. The destination movie might have no sound track, or then these tracks are 
  622.     added to the existing sound tracks.
  623. */
  624.  
  625. pascal OSErr QTUCopySoundTracks(Movie theSrcMovie, Movie theDestMovie)
  626. {
  627.     OSErr     anErr = noErr;
  628.     long        trackCount, index;
  629.     
  630.     DebugAssert(theSrcMovie != NULL); if(theSrcMovie == NULL) return invalidMovie;
  631.     DebugAssert(theDestMovie != NULL); if(theDestMovie == NULL) return invalidMovie;
  632.  
  633.     trackCount = GetMovieTrackCount(theSrcMovie);
  634.     
  635.     // Loop through each track, look for sound tracks.
  636.     for(index = 1; index <= trackCount; index++)
  637.     {
  638.         OSType aTrackType;
  639.         Track    aSrcTrack, aDestTrack;
  640.         Media    aSrcMedia, aDestMedia;
  641.         
  642.         aSrcTrack = GetMovieIndTrack(theSrcMovie, index);            // get next track and media
  643.         aSrcMedia = GetTrackMedia(aSrcTrack);
  644.         anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  645.         if(anErr != noErr) return anErr;
  646.         
  647.         // try to find sound tracks/media
  648.         GetMediaHandlerDescription(aSrcMedia, &aTrackType, 0, 0);
  649.         if(aTrackType == SoundMediaType)
  650.         {
  651.             // Create the track for the sound media.
  652.             aDestTrack = NewMovieTrack(theDestMovie, 0, 0, GetTrackVolume(aSrcTrack));
  653.             anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  654.             if(anErr != noErr) return anErr;
  655.             
  656.             // Create a media for the sound track and prepare this media for editing.
  657.             aDestMedia = NewTrackMedia(aDestTrack, SoundMediaType, GetMediaTimeScale(aSrcMedia), 0, 0);
  658.             anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  659.             if(anErr != noErr) return anErr;
  660.             
  661.             anErr = BeginMediaEdits(aDestMedia); DebugAssert(anErr == noErr);
  662.             if(anErr != noErr) return anErr;
  663.             
  664.             // Insert the new track into the destination movie starting at time zero and
  665.             // lasting for the entire duration of the movie.
  666.             InsertTrackSegment(aSrcTrack, aDestTrack, 0 , GetTrackDuration(aSrcTrack), 0);
  667.             anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  668.             if(anErr != noErr) return anErr;
  669.             
  670.             // We've done editing the media
  671.             EndMediaEdits(aDestMedia);
  672.         }
  673.     }
  674.     return anErr;
  675. }
  676.  
  677.  
  678.  
  679. /*______________________________________________________________________
  680.     QTUPrintMoviePoster - Print the existing movie poster.
  681.  
  682. pascal Boolean QTUPrintMoviePoster(Movie theMovie, short x, short y)
  683.  
  684. theMovie                    movie that has the poster        
  685. x,y                            starting point coordinates where to place the poster on paper
  686.  
  687. DESCRIPTION
  688.     QTUPrintMoviePoster is a simple function showing how to print movie posters. 
  689.  
  690. ISSUES
  691.     Note that in a real application we should put the PrStlDialog code into the Print Setup… menu
  692.     function. The reason it's inside this function is that we use this code for quick testing of 
  693.     printing.
  694. */
  695.  
  696. pascal Boolean QTUPrintMoviePoster(Movie theMovie, short x, short y)
  697. {
  698.     PicHandle     aPictHandle;
  699.     THPrint        aTHPrint;
  700.     GrafPtr         aSavedPort;
  701.     TPPrPort    aPrintPort;
  702.     Boolean     aResult;
  703.     Rect            aPictRect;
  704.     
  705.     DebugAssert(theMovie != NULL);
  706.     if(theMovie == NULL) return false;
  707.     
  708.     GetPort(&aSavedPort);
  709.     
  710.     aPictHandle = GetMoviePosterPict(theMovie); 
  711.     if(aPictHandle == NULL) goto FailureHandling;                  // no movie poster PICT
  712.     
  713.     aTHPrint = (THPrint) NewHandleClear(sizeof(TPrint)); DebugAssert(aTHPrint != NULL);
  714.     if(aTHPrint == NULL) goto FailureHandling;
  715.  
  716.     PrOpen();
  717.     PrintDefault(aTHPrint);
  718.  
  719. // Move this to Print Setup…if you want to make this look really cool.    
  720.     aResult = PrStlDialog(aTHPrint); DebugAssert(aResult == true);
  721.     if(!aResult) goto FailureHandling;
  722.     
  723.     aResult = PrJobDialog(aTHPrint); DebugAssert(aResult == true);
  724.     if(!aResult) goto FailureHandling;
  725.     
  726.     aPrintPort = PrOpenDoc(aTHPrint, NULL, NULL); DebugAssert(aPrintPort != NULL);
  727.     PrOpenPage(aPrintPort, NULL);
  728.     
  729. // Print at x,y position
  730.     aPictRect =  (*aPictHandle)->picFrame;
  731.     OffsetRect(&aPictRect, x - aPictRect.left,  y  - aPictRect.top);
  732.     
  733.     DrawPicture(aPictHandle, &aPictRect);
  734.  
  735. // If you want to do additional drawing, do it here.
  736.     
  737.     PrClosePage(aPrintPort);
  738.     PrCloseDoc(aPrintPort);
  739.     
  740.     if(( *aTHPrint)->prJob.bJDocLoop == bSpoolLoop)
  741.         PrPicFile(aTHPrint, NULL, NULL, NULL, NULL);
  742.     
  743.     PrClose();
  744.  
  745. // Normal behavior, we exit here.    
  746.     return true;
  747.  
  748. // Our failure handling process.
  749. FailureHandling:
  750.     SetPort(aSavedPort);
  751.     
  752.     if(aPictHandle) KillPicture(aPictHandle);
  753.     if(aTHPrint) DisposeHandle((Handle)aTHPrint);
  754.     return false;
  755. }
  756.  
  757.  
  758. // IMAGE COMPRESSION MANAGER
  759.  
  760. /*______________________________________________________________________
  761.     QTUHasCodecLossLessQuality - Test if a specific codec has a lossless mode in a specific bit depth.
  762.  
  763. Boolean QTUHasCodecLossLessQuality(CodecType theCodec, short thePixelDepth)
  764.  
  765. theCodec                        specifies the Codec Type ('jpeg, 'rle ' and so on).
  766. thePixelDepth                specifies the bit depth (8, 24, 30 and so on). See NIM:QuickTime, page 
  767.                                     3-70 for more details.
  768.  
  769. DESCRIPTION
  770.     QTUHasCodecLossLessQuality will test if a specific codec has a lossless spatial compression 
  771.     quality at a certain bit depth. Note that we are not testing the temporal compression qualities.
  772.  
  773. EXAMPLE OF USE:
  774.     if(QTUHasCodecLossLessQuality('jpeg', 32))  
  775.         printf("JPEG has lossless spatial compression\n");
  776.     else
  777.         printf("JPEG has NOT lossless spatial compression\n");
  778.  
  779. */
  780.  
  781. Boolean QTUHasCodecLossLessQuality(CodecType theCodec, short thePixelDepth)
  782. {
  783.     CodecQ    aSpatialQuality = codecLosslessQuality;
  784.     OSErr     anErr;
  785.  
  786.     anErr = GetCompressionTime(NULL, NULL, thePixelDepth, theCodec, anyCodec, &aSpatialQuality,
  787.                         NULL, NULL); DebugAssert(anErr == noErr);
  788.     
  789.     if(aSpatialQuality == codecLosslessQuality)    // still the same?
  790.         return true;
  791.     else
  792.         return false;
  793. }
  794.  
  795.  
  796.  
  797. // MOVIE CONTROLLER FUNCTIONS
  798.  
  799.  
  800. /*______________________________________________________________________
  801.     QTUPlayMovieWithMC - Play a specific movie when using movie controllers.
  802.  
  803. pascal OSErr QTUPlayMovieWithMC(Movie theMovie, MovieController mc)
  804.  
  805. theMovie                specifies the destination movie for this operation
  806. mc                        specified movie controller to be used
  807.  
  808. DESCRIPTION
  809.     Playmovie will start a movie using a moviecontroller and a specified movie. Note that it also  
  810.     does a preroll of the movie for performance reasons. 
  811.  
  812. */
  813.  
  814. pascal OSErr QTUPlayMovieWithMC(Movie theMovie, MovieController mc)
  815. {
  816. // Play normal speed forward, taking into account the possibility 
  817. // of a movie with a nonstandard PreferredRate.
  818.     Fixed     aRate;
  819.     OSErr    anErr = noErr;
  820.  
  821.     aRate= GetMoviePreferredRate(theMovie);
  822.     anErr = QTUPrerollMovie(theMovie);  // Important: Preroll the movie here.
  823.     DebugAssert(anErr == noErr);
  824.  
  825.     if(anErr == noErr)
  826.     {
  827.         MCDoAction(mc, mcActionPlay, (void *)aRate);  // note last value
  828.     }
  829.     
  830.     return anErr;
  831. }
  832.  
  833.  
  834. /*______________________________________________________________________
  835.     QTUDoIgnoreMCDrags - Disable Drag and Drop facilities of the movie controller environment.
  836.  
  837. pascal OSErr  QTUDoIgnoreMCDrags(MovieController  mc)
  838.  
  839. mc                        is the specified moviecontroller to be used
  840.  
  841. DESCRIPTION
  842.     QTUDoIgnoreMCDrags will ensure that the Drag and Drop functionality is not handled within 
  843.     the movie specified by the movie controller.
  844.  
  845. ISSUES
  846.     Note that this is a workaround in QT 2.0 (test for QT 2.0 or higher if you want to use
  847.     the drag-and-drop support in QT), and this function might not be needed in later QT versions.
  848. */
  849.  
  850. pascal OSErr QTUDoIgnoreMCDrags(MovieController  mc)
  851. {
  852.    GWorldPtr  aTempGWorld;
  853.    Rect             aTempRect = {0, 0, 20, 20};
  854.    OSErr           anErr = noErr;
  855.    CGrafPtr     aPort;
  856.  
  857.    // First create a 1-bit small 20x20 offscreen.
  858.    anErr = NewGWorld( &aTempGWorld, 1, &aTempRect, NULL, NULL, 0L );
  859.    DebugAssert(anErr == noErr);
  860.  
  861.    if (anErr != noErr)
  862.    {
  863.            aPort = MCGetControllerPort(mc);                                    // get the current port
  864.            MCSetControllerPort(mc, (CGrafPtr)aTempGWorld );        // set mc port to new offscreen
  865.            MCDoAction(mc, mcActionSetDragEnabled, (void *)false); // don't want dragging
  866.           MCSetControllerPort(mc, aPort);                                        // restore mc port
  867.            DisposeGWorld(aTempGWorld);                                            // dispose offscreen
  868.    }
  869.    return anErr;
  870. }
  871.  
  872.  
  873. /*______________________________________________________________________
  874.     QTUPointInMC - Test if a point is placed in the movie controller rect area or not.
  875.  
  876. pascal Boolean QTUPointInMC(MovieController mc, WindowRef theWindow, Point where)
  877.  
  878. mc                            is the specified moviecontroller to be used
  879. theWindow                window used for testing for the hit point
  880. where                        hit point
  881.  
  882. DESCRIPTION
  883.     QTUPointInMC is a simple test to check where the mouse was clicked inside the window
  884.     with a movie controller, returns true of the mouse click was inside the movie controller
  885.     rect. See Peter Hoddie's article in develop# 18 for more details (code is from him as well).
  886. */
  887.  
  888. pascal Boolean QTUPointInMC(MovieController mc, WindowRef theWindow, Point where)
  889. {
  890.     RgnHandle    aRegion;
  891.     Boolean        result = false;
  892.     
  893.     aRegion = MCGetWindowRgn(mc, theWindow);
  894.        DebugAssert(aRegion != NULL);
  895.     
  896.     if(aRegion != NULL)
  897.     {
  898.         result = PtInRgn(where, aRegion);
  899.         DisposeRgn(aRegion);
  900.     }
  901.     
  902.     return result;
  903. }
  904.  
  905.  
  906. /*______________________________________________________________________
  907.     QTUSelectAllMovie - Select the whole movie time duration with the controller.
  908.  
  909. pascal OSErr QTUSelectAllMovie(MovieController mc)
  910.  
  911. mc                        is the specified moviecontroller to be used
  912.  
  913. DESCRIPTION
  914.     QTUSelectAllMovie is an example how to select the whole movie duration using the movie
  915.     controller, this function could be used for Select All menu entries and similar cases.
  916. */
  917.  
  918. pascal OSErr QTUSelectAllMovie(MovieController mc)
  919. {
  920.     TimeRecord  aTimeRecord;
  921.     Movie aMovie = NULL;
  922.     OSErr anErr = noErr;
  923.     
  924.     DebugAssert(mc != NULL);
  925.     if(mc == NULL) return paramErr;
  926.     
  927.     aMovie = MCGetMovie(mc); DebugAssert(aMovie != NULL);
  928.     if(aMovie == NULL) return paramErr;
  929.     
  930.     aTimeRecord.value.hi = 0;
  931.     aTimeRecord.value.lo = 0;
  932.     aTimeRecord.base = 0;
  933.     
  934.     aTimeRecord.scale = GetMovieTimeScale(aMovie);
  935.     anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  936.     if(anErr != noErr) return anErr;
  937.     
  938.     anErr = MCDoAction(mc, mcActionSetSelectionBegin, &aTimeRecord);
  939.     DebugAssert(anErr == noErr);
  940.     if(anErr != noErr) return anErr;
  941.     
  942.     aTimeRecord.value.lo = GetMovieDuration(aMovie);
  943.     anErr = GetMoviesError(); DebugAssert(anErr == noErr);
  944.     if(anErr != noErr) return anErr;
  945.     
  946.     anErr = MCDoAction(mc, mcActionSetSelectionDuration, &aTimeRecord);
  947.     DebugAssert(anErr == noErr);
  948.     
  949.     return anErr;
  950. }
  951.  
  952.  
  953. /*______________________________________________________________________
  954.      QTUResizeMCActionFilter - Example of a movie controller filter that will resize the window 
  955.     where the movie is placed when the controllers themself change. 
  956.  
  957. pascal Boolean QTUResizeMCActionFilter(MovieController mc, short action, void *params, long refCon)
  958.  
  959. mc                            specified moviecontroller to be used.
  960. action                        the action for the mc action filter
  961. params                        parameters passed with the action
  962. refCon                      additional long word that could be used for all kinds of purposes
  963.  
  964. DESCRIPTION
  965.     QTUResizeMCActionFilter is an example of how to create a nice movie controller filter that 
  966.     will handle resizing of the window with the movie, and this will happen every time the controllers
  967.     themselves change. It's also an example of how to write other kinds of movie controller filters.
  968. */
  969.  
  970. pascal Boolean QTUResizeMCActionFilter(MovieController mc, short action, void *params, long refCon)
  971. {
  972.     Rect aMovieBounds;
  973.     
  974.     switch(action)
  975.     {
  976.         case mcActionControllerSizeChanged:
  977.             MCGetControllerBoundsRect(mc, &aMovieBounds);
  978.             SizeWindow((WindowPtr) refCon, aMovieBounds.right - aMovieBounds.left,
  979.                                 aMovieBounds.bottom - aMovieBounds.top, true);
  980.             break;
  981.     }
  982.         return false;
  983. }
  984.  
  985.  
  986. /*______________________________________________________________________
  987.     QTUResizeMCWindow - Resize a window to either normal size, double size or  half of the movie rect size.
  988.  
  989. pascal Boolean QTUResizeMCWindow(MovieController mc, WindowPtr theWindow, long theMovieSize, Rect originalSize)
  990.  
  991. mc                                specified moviecontroller to be used
  992. theWindow                    window that will be resized
  993. theMovieSize                constant that defines what default size we are interested in,  kNormalSize, kHalfSize, kDoubleSize
  994. originalSize                    the original size of the movie, we need to keep track of this one in order to handle the 
  995.                                      ambient new sizes (half, double, normal).
  996.  
  997. DESCRIPTION
  998.     QTUResizeMCWindow is an example of a function how to resize the movie window with the controllers.
  999.     The most common cases is half size, normal size or double size. But nothing hinders to add more sizes
  1000.     into this function. Note that if the movie window is doubled, we will get pixel-doubling by the QuickTime
  1001.     engine.
  1002. */
  1003.  
  1004. pascal OSErr QTUResizeMCWindow(MovieController mc, WindowPtr theWindow, long theMovieSize, Rect originalSize)
  1005. {
  1006.     Rect aMovieBounds;
  1007.     GrafPtr aSavedPort;
  1008.     OSErr anErr = noErr;
  1009.     
  1010.     DebugAssert(mc != NULL); if(mc == NULL) return paramErr;
  1011.     DebugAssert(theWindow != NULL); if(theWindow == NULL) return paramErr;
  1012.     
  1013.     GetPort(&aSavedPort);
  1014.     SetPort((GrafPtr)theWindow);
  1015.     
  1016.     aMovieBounds.top = 0; aMovieBounds.left = 0;
  1017.  
  1018.     switch(theMovieSize)
  1019.     {
  1020.         case kNormalMovieSize:
  1021.                 MCSetControllerBoundsRect(mc, &originalSize);
  1022.                 SizeWindow(theWindow, originalSize.right, originalSize.bottom, true);
  1023.             break;
  1024.         
  1025.         case kHalfMovieSize:
  1026.                 aMovieBounds.right = (originalSize.right - originalSize.left) / 2;
  1027.                 aMovieBounds.bottom = (originalSize.bottom - originalSize.top) / 2;
  1028.                 MCSetControllerBoundsRect(mc, &aMovieBounds);
  1029.                 SizeWindow(theWindow, aMovieBounds.right, aMovieBounds.bottom, true);
  1030.             break;
  1031.         
  1032.         case kDoubleMovieSize:
  1033.                 aMovieBounds.right = (originalSize.right - originalSize.left) * 2;
  1034.                 aMovieBounds.bottom = (originalSize.bottom - originalSize.top) * 2;
  1035.                 MCSetControllerBoundsRect(mc, &aMovieBounds);
  1036.                 SizeWindow(theWindow, aMovieBounds.right, aMovieBounds.bottom, true);
  1037.             break;
  1038.         
  1039.         default:
  1040.             SetPort(aSavedPort);
  1041.             anErr = paramErr;
  1042.     }
  1043.     
  1044.     SetPort(aSavedPort);
  1045.     return anErr;
  1046. }
  1047.  
  1048.  
  1049. /*______________________________________________________________________
  1050.     QTUResizeMCWindow -Change the movie rate using the movie controller. 
  1051.  
  1052. pascal OSErr QTUMCSetMovieRate(MovieController mc, long theRate)
  1053.  
  1054. mc                            specified moviecontroller to be used
  1055. theRate                        new rate value, we are using specific constants, see the eQTUMovieRates enum
  1056.                                 in the DTSQTUtilities.h file concerning the values.
  1057.  
  1058. DESCRIPTION
  1059.     QTUMCSetMovieRate will use an existing movie controller and change the rate. This is a very 
  1060.     simple function, but we do have a list of constants that shows the various values that could be used 
  1061.     (eQTUMovieRates, DTSQTUtilities.h), and also it shows that if the rate changes from 0 to something 
  1062.     else, then we need to preroll the movie. The Apple MM Tuner will make sure the movie is prerolled,
  1063.     but we can't assume that every Mac has this extension installed, that's why it's still very important
  1064.     to preroll.
  1065.     
  1066. ISSUES
  1067.     Note that movies have stored preferred rates, so if you want to compensate for this factor you need
  1068.     to read in this value as well before setting a double or half speed value.
  1069. */
  1070.  
  1071. pascal OSErr QTUMCSetMovieRate(MovieController mc, long theRate)
  1072. {
  1073.     OSErr     anErr = noErr;
  1074.     Fixed     aRate;
  1075.     
  1076.     DebugAssert(mc != NULL); 
  1077.     
  1078.     // Test if the playrate changes from 0 to a non-zero value, if so then preroll the movie.
  1079.     MCDoAction(mc, mcActionGetPlayRate, &aRate);
  1080.     if( (aRate == 0) && (theRate != 0) )
  1081.     {
  1082.         anErr = QTUPrerollMovie(MCGetMovie(mc));            // we are using the DTSQTUtilities function
  1083.         DebugAssert(anErr == noErr);
  1084.         if(anErr != noErr) return anErr;
  1085.     }
  1086.         
  1087.     anErr = MCDoAction(mc, mcActionPlay, (Ptr) theRate); DebugAssert(anErr == noErr);
  1088.     
  1089.     return anErr;
  1090. }
  1091.  
  1092.  
  1093. // COMPONENT FUNCTIONS
  1094.  
  1095. /*______________________________________________________________________
  1096.     QTUDoGetComponent - Get a specific component based on component type and component sub-type.
  1097.  
  1098. pascal Component QTUDoGetComponent(OSType theComponentType, OSType theSpecificComponent)
  1099.  
  1100. theComponentType                    the component type we are interested in
  1101. theSpecificComponent                the specific component sub-type we are interested int
  1102.  
  1103. DESCRIPTION
  1104.     QTUDoGetComponent will get a specific component based on the component type and sub-type.  We have 
  1105.     special code for particular components (for instance movieImporttype and movieExporttype), so
  1106.     if we specify such types, the function will narrow down the search further for the right components.
  1107.     
  1108.     The specificComponent is just the special component we want to search for, if the component type is 
  1109.     NULL, then the Specific component is the one and only we are interested in. Note that we don't care 
  1110.     about the manufacturer information in this function. 
  1111.     
  1112.     If we don't find a suitable component we will return NULL.
  1113. */
  1114.  
  1115. pascal Component QTUDoGetComponent(OSType theComponentType, OSType theSpecificComponent)
  1116. {
  1117.     ComponentDescription aCD;
  1118.     Component aComponent = NULL;
  1119.     
  1120.     aCD.componentType = theComponentType;
  1121.     aCD.componentSubType = theSpecificComponent;
  1122.     aCD.componentManufacturer = 0;
  1123.     
  1124.     // The following code is inserted for special handling of some known cases.
  1125.     if(theComponentType == MovieImportType)
  1126.     {
  1127.         aCD.componentFlags = canMovieImportFiles;
  1128.         aCD.componentFlagsMask = canMovieImportFiles;
  1129.     }
  1130.     else if(theComponentType == MovieExportType)
  1131.     {
  1132.         aCD.componentFlags = canMovieExportFiles;
  1133.         aCD.componentFlagsMask = canMovieExportFiles;
  1134.     }
  1135.  
  1136.     // OK, get the component.
  1137.     aComponent = FindNextComponent((Component)0, &aCD);
  1138.     
  1139.     return aComponent;
  1140. }
  1141.  
  1142.  
  1143. /*______________________________________________________________________
  1144.     QTUHasComponentType -Query for a specific component based on component type and 
  1145.     component sub-type.
  1146.  
  1147. pascal Boolean QTUHasComponentType(OSType theComponentType, OSType theSpecificComponent)
  1148.  
  1149. theComponentType                    the component type we are interested in
  1150. theSpecificComponent                the specific component sub-type we are interested int
  1151.  
  1152. DESCRIPTION
  1153.     QTUDoGetComponent will query for a specific component based on the component type and sub-type.  
  1154.     We have special code for particular components (for instance movieImporttype and movieExporttype),
  1155.     so if we query for such types, the function will narrow down the search further for the right 
  1156.     components.
  1157.     
  1158.     The specificComponent is just the special component we want to search for, if the component 
  1159.     type is NULL, then the Specific component is the one and only we are interested in. Note that we 
  1160.     don't care about the manufacturer information in this function. 
  1161.     
  1162.     If we don't find a suitable component we will return false, otherwise we will return true.
  1163. */
  1164.  
  1165. pascal Boolean QTUHasComponentType(OSType theComponentType, OSType theSpecificComponent)
  1166. {
  1167.     ComponentDescription aCD;
  1168.     
  1169.     aCD.componentType = theComponentType;
  1170.     aCD.componentSubType = theSpecificComponent;
  1171.     aCD.componentManufacturer = 0;
  1172.     
  1173.     if(theComponentType == MovieImportType)
  1174.     {
  1175.         aCD.componentFlags = canMovieImportFiles;
  1176.         aCD.componentFlagsMask = canMovieImportFiles;
  1177.     }
  1178.     else if(theComponentType == MovieExportType)
  1179.     {
  1180.         aCD.componentFlags = canMovieExportFiles;
  1181.         aCD.componentFlagsMask = canMovieExportFiles;
  1182.     }
  1183.  
  1184.     if(FindNextComponent((Component)0, &aCD) != NULL)
  1185.         return true;
  1186.     else
  1187.         return false;
  1188. }
  1189.  
  1190.  
  1191. //______________________________________________________________________
  1192. // T H E    E N D